﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using BTM_Client_Application.RealTimeFilter;
using BTM_Client_Application.SupportClasses;
using Client_Server_Interface;

namespace BTM_Client_Application
{
    /// <summary>
    /// Логика взаимодействия для LogControl.xaml
    /// </summary>
    public partial class LogControl
    {
        private DataGridAutoInitFilter<LogRecord>   _filter;
        private ObservableCollection<LogRecord>     _records;

        public String Title { get; private set; }

        public LogControl()
        {
            InitializeComponent();
            Initialize();
            UiLanguageChanged();
        }

        void Initialize()
        {
            _records = new ObservableCollection<LogRecord>();
            List<DataGridColumn> cols;
            _filter = new DataGridAutoInitFilter<LogRecord>(new LogRecord(), ref _records, out cols);
            foreach (var column in cols)
            {
                LogGrid.Columns.Add(column);
            }
            LogGrid.ItemsSource = _records;
            FilterContainer.Children.Add(_filter.FilterControl);

            LogContextMenu.AppendMenu(ref LogGrid, ref _filter);
        }

        private void LogControl_OnInitialized(object sender, EventArgs e)
        {
        }

        public void UiLanguageChanged()
        {
            Title = Res.Rm.GetString("Log", AliveInfo.CurrentCulture);
            //LogRefreshButton.Content = new ButtonWithImage((BitmapImage)FindResource("RefreshLight"), Res.Rm.GetString("Refresh"));
            LogRefreshButtonContainer.Children.Clear();
            LogRefreshButtonContainer.Children.Add(new ButtonWithImage((BitmapImage) FindResource("RefreshDark"),
                                                                       Res.Rm.GetString("Refresh", AliveInfo.CurrentCulture),
                                                                       LogRefreshButton_OnClick));

            FilterClearButtonContainer.Children.Clear();
            FilterClearButtonContainer.Children.Add(new ButtonWithImage((BitmapImage)FindResource("ResetDark"),
                                                                       Res.Rm.GetString("Reset", AliveInfo.CurrentCulture),
                                                                       FilterClearButton_OnClick));

            GraphButtonContainer.Children.Clear();
            GraphButtonContainer.Children.Add(new ButtonWithImage((BitmapImage)FindResource("GraphLineDark"),
                                                                       Res.Rm.GetString("Graph", AliveInfo.CurrentCulture),
                                                                       GraphButton_OnClick));

            //LogRefreshButton.Content = Res.Rm.GetString("Refresh", AliveInfo.CurrentCulture);
            //FilterClearButton.Content = Res.Rm.GetString("Clear", AliveInfo.CurrentCulture);
            //GraphButton.Content = Res.Rm.GetString("Graph", AliveInfo.CurrentCulture);
        }

        private void LogRefreshButton_OnClick(object sender, RoutedEventArgs e)
        {
            UpdateLog();
        }

        private void UpdateLog()
        {
            var something = _filter.GetRequestValues();
            UpdateLog(something);
        }

        

        //ToImprove
        public void UpdateLog(Dictionary<string, List<object>> req)
        {
            
            //var list = LogRecord.GetLogData(req);
            _records.Clear();
            /*var events = new List<object>();
            try
            {
                events = req[LogRecord.EventTitle];
            }
            catch (Exception)
            {

            }
            

            foreach (var record in list)
            {
                const int regionPos = 0;
                const int blrPos = 1;
                const int devicePos = 2;
                const int stationPos = 3;
                const int severityPos = 4;
                const int eventPos = 5;
                const int sourcePos = 6;
                const int infoPos = 7;
                const int timePos = 8;

                var props = record.Split(new[] { ';' }, StringSplitOptions.None);
                DateTime date;
                try
                {
                    date = DateTime.Parse(props[timePos]);
                }
                catch (Exception)
                {
                    continue;
                }

                var lRecord = new LogRecord(props[regionPos], props[blrPos], props[devicePos], props[stationPos],
                                            props[severityPos], props[eventPos], props[sourcePos], props[infoPos],
                                            date);
                switch (lRecord.Severity)
                {
                    case ErrorStatus.CRITICAL:
                        lRecord.ItemBackground = Res.StatusColor.Critical;
                        break;
                    case ErrorStatus.ALARM:
                        lRecord.ItemBackground = Res.StatusColor.Alarm;
                        break;
                    case ErrorStatus.WARNING:
                        lRecord.ItemBackground = Res.StatusColor.Warning;
                        break;
                    case ErrorStatus.MINOR:
                        lRecord.ItemBackground = Res.StatusColor.Minor;
                        break;
                    case ErrorStatus.INDETERMINATE:
                        lRecord.ItemBackground = Res.StatusColor.Indeterminate;
                        break;
                    default:
                        lRecord.ItemBackground = new SolidColorBrush(Colors.Transparent);
                        break;
                }
                //Filter events
                bool contains = true;
                if (events.Count > 0)
                {
                    contains = false;
                    if (!events.Contains(lRecord.Event))
                    {
                        if (events.Cast<string>().Any(ev => lRecord.Event.Contains(ev)))
                        {
                            contains = true;
                        }
                    }
                    else
                    {
                        contains = true;
                    }
                }
                if(contains)
                    _records.Add(lRecord);
            }*/
            List<LogRecord> l;
            try
            {
                //Получение списка ошибок для отображения
                l = LogRecord.WorkLogData(req, logRecordWork);
            }
            catch (ClientException ex)
            {
                if (ex.AdditionalInfo == ClientExceptionMessage.EMPTY)
                    MessageBox.Show(Res.Rm.GetString("NothingFound", AliveInfo.CurrentCulture));
                return;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Res.Rm.GetString("Warning", AliveInfo.CurrentCulture));
                return;
            }
            
            foreach (var record in l)
            {
                _records.Add(record);
            }
        }

        //Что сделать с полученным список ошибок
        private LogRecord logRecordWork(LogRecord lRecord, Dictionary<string, List<object>> req)
        {
            switch (lRecord.Severity)
            {
                case ErrorStatus.CRITICAL:
                    lRecord.ItemBackground = Res.StatusColor.Critical;
                    break;
                case ErrorStatus.ALARM:
                    lRecord.ItemBackground = Res.StatusColor.Alarm;
                    break;
                case ErrorStatus.WARNING:
                    lRecord.ItemBackground = Res.StatusColor.Warning;
                    break;
                case ErrorStatus.MINOR:
                    lRecord.ItemBackground = Res.StatusColor.Minor;
                    break;
                case ErrorStatus.INDETERMINATE:
                    lRecord.ItemBackground = Res.StatusColor.Indeterminate;
                    break;
                default:
                    lRecord.ItemBackground = new SolidColorBrush(Colors.Transparent);
                    break;
            }
            return lRecord;
        }

        /*
        private static StringBuilder ParameterslistToString(IEnumerable<object> list)
        {
            var sb = new StringBuilder();
            foreach (var o in list)
            {
                sb.Append(o + ",");
            }
            if(sb.Length > 0)
                sb.Remove(sb.Length - 1, 1);
            return sb;
        }*/

        private void FilterClearButton_OnClick(object sender, RoutedEventArgs e)
        {
            _filter.ClearFilter();
            UpdateLog();
            //_records.Clear();
        }

        /*
        public class LogRecord : IRealTimeFilterObject
        {

            #region props
            private static readonly string _regionTitle = Res.Rm.GetString("Region");
            private static readonly string _blrTitle = Res.Rm.GetString("FrequencyZone");
            private static readonly string _stationTitle = Res.Rm.GetString("Station");
            private static readonly string _deviceTitle = Res.Rm.GetString("Device");

            private static readonly string _severityTitle = Res.Rm.GetString("Severity");
            private static readonly string _eventTitle = Res.Rm.GetString("Event");
            private static readonly string _sourceTitle = Res.Rm.GetString("Source");
            private static readonly string _infoTitle = Res.Rm.GetString("Info");

            private static readonly string _startTimeTitle = Res.Rm.GetString("StartTime");
            private static readonly string _endTimeTitle = Res.Rm.GetString("EndTime");

            private static readonly string _timeTitle = Res.Rm.GetString("Time");
            private static readonly string _infoGridColumnTitle = Res.Rm.GetString("AdditionalInfo");
            
            public static string RegionTitle
            {
                get { return _regionTitle; }
            }

            public static string BlrTitle
            {
                get { return _blrTitle; }
            }

            public static string StationTitle
            {
                get { return _stationTitle; }
            }

            public static string DeviceTitle
            {
                get { return _deviceTitle; }
            }

            public static string SeverityTitle
            {
                get { return _severityTitle; }
            }

            public static string EventTitle
            {
                get { return _eventTitle; }
            }

            public static string SourceTitle
            {
                get { return _sourceTitle; }
            }

            public static string InfoTitle
            {
                get { return _infoTitle; }
            }

            public static string StartTimeTitle
            {
                get { return _startTimeTitle; }
            }

            public static string EndTimeTitle
            {
                get { return _endTimeTitle; }
            }

            public static List<string> GetLogData(Dictionary<string, List<object>> req)
            {
                var regions = new StringBuilder("");
                if (req.ContainsKey(LogRecord.RegionTitle))
                    regions = ParameterslistToString(req[LogRecord.RegionTitle]);

                var blrs = new StringBuilder("");
                if (req.ContainsKey(LogRecord.BlrTitle))
                    blrs = ParameterslistToString(req[LogRecord.BlrTitle]);

                var stations = new StringBuilder("");
                if (req.ContainsKey(LogRecord.StationTitle))
                    stations = ParameterslistToString(req[LogRecord.StationTitle]);

                var devices = new StringBuilder("");
                if (req.ContainsKey(LogRecord.DeviceTitle))
                    devices = ParameterslistToString(req[LogRecord.DeviceTitle]);

                StringBuilder logData = AliveInfo.ClientHelper.GetLogFromServer(regions.ToString(), blrs.ToString(), stations.ToString(),
                                                                                devices.ToString(),
                                                                                (DateTime)req[LogRecord.StartTimeTitle][0],
                                                                                (DateTime)(req[LogRecord.EndTimeTitle][0]));
                var st = logData.ToString();
                return st.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).ToList();
            }

            #endregion

            static LogRecord()
            {

                var availableDevices = new List<object>(AliveInfo.MegaDeviceTree.Devices.Count);

                foreach (var device in AliveInfo.MegaDeviceTree.Devices.OrderBy(x => x.DevInfo.Title))
                {
                    availableDevices.Add(device.DevInfo.Title);
                }

                var availableStations = new List<object>(AliveInfo.MegaDeviceTree.Stations.Count);

                foreach (var station in AliveInfo.MegaDeviceTree.Stations.OrderBy(x => x.Info.Station))
                {
                    availableStations.Add(station.Info.Station);
                }

                var availableRegions = new List<object>(AliveInfo.MegaDeviceTree.Regions.Count);

                foreach (var region in AliveInfo.MegaDeviceTree.Regions.OrderBy(x => x.ToString(CultureInfo.InvariantCulture)))
                {
                    availableRegions.Add(region);
                }

                var availableBlrs = new List<object>(AliveInfo.MegaDeviceTree.Blrs.Count);

                foreach (var blr in AliveInfo.MegaDeviceTree.Blrs.OrderBy(x => x.ToString(CultureInfo.InvariantCulture)))
                {
                    availableBlrs.Add(blr);
                }

                _filterInterface = new Dictionary<string, FilterElementInitializer>();
                _filterInterface.Add(_regionTitle,
                                     new FilterElementInitializer(FilterElementType.StringList, availableRegions,
                                                                  new DataGridColumnInitializer(_regionTitle, "Region")));
                _filterInterface.Add(_blrTitle,
                                     new FilterElementInitializer(FilterElementType.StringList, availableBlrs,
                                                                  new DataGridColumnInitializer(_blrTitle, "Blr")));
                _filterInterface.Add(_stationTitle,
                                     new FilterElementInitializer(FilterElementType.StringList, availableStations,
                                                                  new DataGridColumnInitializer(_stationTitle, "Station")));
                _filterInterface.Add(_deviceTitle,
                                     new FilterElementInitializer(FilterElementType.StringList, availableDevices,
                                                                  new DataGridColumnInitializer(_deviceTitle, "Device")));
                _filterInterface.Add(_severityTitle,
                                     new FilterElementInitializer(FilterElementType.NoControl, null,
                                                                  new DataGridColumnInitializer(_severityTitle, "Severity")));
                _filterInterface.Add(_eventTitle,
                                     new FilterElementInitializer(FilterElementType.StringListContains, null,
                                                                  new DataGridColumnInitializer(_eventTitle, "Event")));
                _filterInterface.Add(_sourceTitle,
                                     new FilterElementInitializer(FilterElementType.NoControl, null,
                                                                  new DataGridColumnInitializer(_sourceTitle, "Source")));
                _filterInterface.Add(_infoTitle,
                                     new FilterElementInitializer(FilterElementType.NoControl, null,
                                                                  new DataGridColumnInitializer(_infoGridColumnTitle, "Info")));
                _filterInterface.Add(_startTimeTitle,
                                     new FilterElementInitializer(FilterElementType.StartTime, null,
                                                                  new DataGridColumnInitializer(_timeTitle, "StartTime")));
                _filterInterface.Add(_endTimeTitle,
                                     new FilterElementInitializer(FilterElementType.EndTime, null, null));

                _filterElements = new Dictionary<string, object>();
            }

            public LogRecord()
            {
                
            }

            public LogRecord(string region, string blr, string device, string station, string severity, string eventData, string source, string info, DateTime startTime)
            {
                Region = region;
                Blr = blr;
                Station = station;
                Device = device;
                Severity = severity;
                StartTime = startTime;
                Event = eventData;
                Source = source;
                Info = info;
            }

            public Brush ItemBackground { get; set; }

            public string Region { get; private set; }
            public string Blr { get; private set; }
            public string Device { get; private set; }
            public string Station { get; private set; }
            public string Severity { get; private set; }
            public string Event { get; private set; }
            public string Source { get; private set; }
            public string Info { get; private set; }

            //ToRepair
            public DateTime StartTime { get; private set; }
            public string EndTime { get; private set; }

            public override int GetHashCode()
            {
                return Region.GetHashCode() ^ Blr.GetHashCode() ^ Device.GetHashCode() ^ Station.GetHashCode() ^
                       Severity.GetHashCode() ^ Event.GetHashCode() ^ Source.GetHashCode() ^ Info.GetHashCode() ^
                       StartTime.GetHashCode();
            }

            public override bool Equals(object obj)
            {
                var another = obj as LogRecord;
                if (another == null)
                    return false;
                return another.GetHashCode() == GetHashCode();
            }

// ReSharper disable InconsistentNaming
            private static readonly Dictionary<string, FilterElementInitializer> _filterInterface;
            private static readonly Dictionary<string, object> _filterElements;
// ReSharper restore InconsistentNaming

            public Dictionary<string, FilterElementInitializer> FilterInterface { get { return _filterInterface; } }
            public Dictionary<string, object> FilterElements { get { return _filterElements; } }

        }
        */

        class LogContextMenu
        {
            private readonly ContextMenu _menu;
            private readonly DataGrid _grid;
            private readonly DataGridAutoInitFilter<LogRecord> _logFilter;

            private LogContextMenu()
            {
                _menu = new ContextMenu
                    {
                        FontFamily = new FontFamily("Segoe UI")
                    };
                var selectionItem = new MenuItem {Header = Res.Rm.GetString("Selection", AliveInfo.CurrentCulture)};
                selectionItem.Click += SelectionItemOnClick;

                var graphItem = new MenuItem {Header = Res.Rm.GetString("Graph", AliveInfo.CurrentCulture)};
                graphItem.Click += GraphItemOnClick;

                _menu.Items.Add(selectionItem);
                _menu.Items.Add(graphItem);
            }

            private LogContextMenu(ref DataGrid grid, ref DataGridAutoInitFilter<LogRecord> filter) : this()
            {
                _grid = grid;
                _logFilter = filter;
                grid.ContextMenu = _menu;
            }

            //Graph of events
            private void GraphItemOnClick(object sender, RoutedEventArgs routedEventArgs)
            {
                GraphWork();
            }

            //Selection of events
            private void SelectionItemOnClick(object sender, RoutedEventArgs routedEventArgs)
            {
                SelectionWork();
            }

            //not implemented
            private void GraphWork()
            {
                //errorsList
                var list = GetSelectedEvents();
                //filterParameters
                var reqv = _logFilter.GetRequestValues();
                var gc = new GraphControl();
                gc.PlotFromValues(list, reqv);
                AliveInfo.MainWindow.AppendTab(MainWindow.TabType.Graph, gc);
            }

            private void SelectionWork()
            {
                var reqv = _logFilter.GetRequestValues();
                var newlc = new LogControl();
                newlc._filter.SetFilterActiveValues(LogRecord.EventTitle, FilterElementType.StringList, GetSelectedEvents());
                newlc._filter.SetFilterActiveValues(LogRecord.StartTimeTitle, FilterElementType.StartTime, reqv[LogRecord.StartTimeTitle]);
                newlc._filter.SetFilterActiveValues(LogRecord.EndTimeTitle, FilterElementType.EndTime, reqv[LogRecord.EndTimeTitle]);
                newlc.UpdateLog();

                AliveInfo.MainWindow.AppendTab(MainWindow.TabType.Log,  newlc);
            }

            private List<object> GetSelectedEvents()
            {
                var errors = new List<object>(_grid.SelectedItems.Count);
                foreach (var item in _grid.SelectedItems)
                {
                    var record = item as LogRecord;
                    errors.Add(record.Event);
                }
                return errors.Distinct().OrderBy(x => x.ToString()).ToList();
            }

            public static void AppendMenu(ref DataGrid grid, ref DataGridAutoInitFilter<LogRecord> filter)
            {
                new LogContextMenu(ref grid, ref filter);
            }

        }

        private void GraphButton_OnClick(object sender, RoutedEventArgs e)
        {
            var gc = new GraphControl();
            try
            {
                gc.PlotFromValues(null, _filter.GetRequestValues());
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Res.Rm.GetString("Warning", AliveInfo.CurrentCulture));
                return;
            }
            
            AliveInfo.MainWindow.AppendTab(MainWindow.TabType.Graph, gc);
        }
    }


}
